﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.OleDb;
using System.Linq;
using System.Web;

namespace FlyingCircusWebIS.Models
{
    public class ReservaDAO: IReservaDAO
    {
        private IPessoaDAO pessoaDAO;
        private ICupomDAO cupomDAO;
        private IFormaPagamentoDAO formaPagamentoDAO;
        private IVooDAO vooDAO;

        public ReservaDAO()
        {
            pessoaDAO = new PessoaDAO();
            cupomDAO = new CupomDAO();
            formaPagamentoDAO = new FormaPagamentoDAO();
            vooDAO = new VooDAO();
        }


        public void Adicionar(Reserva entidade, DbTransaction transacao)
        {
            string sqlInserir = "insert into RESERVA (IdReserva, NumAssento, PrecoReserva, DataVenda, IdPessoaCliente, IdVoo, CodCupom, IdPagamento) values (seqRESERVA.NEXTVAL, ?, ?, ?, ?, ?, ?, ?)";

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlInserir;
            if (transacao != null)
                comando.Transaction = transacao as OleDbTransaction;

            OleDbParameter pNumAssento = new OleDbParameter("NumAssento", OleDbType.Integer);
            pNumAssento.Value = entidade.NumAssento;
            comando.Parameters.Add(pNumAssento);

            OleDbParameter pPrecoReserva = new OleDbParameter("PrecoReserva", OleDbType.Numeric);
            pPrecoReserva.Value = entidade.PrecoReserva;
            comando.Parameters.Add(pPrecoReserva);

            OleDbParameter pDataVenda = new OleDbParameter("DataVenda", OleDbType.Date);
            pDataVenda.Value = entidade.DataVenda;
            comando.Parameters.Add(pDataVenda);

            OleDbParameter pIdPessoaCliente = new OleDbParameter("IdPessoaCliente", OleDbType.Integer);
            pIdPessoaCliente.Value = entidade.IdPessoaCliente;
            comando.Parameters.Add(pIdPessoaCliente);

            OleDbParameter pIdVoo = new OleDbParameter("IdVoo", OleDbType.Integer);
            pIdVoo.Value = entidade.IdVoo;
            comando.Parameters.Add(pIdVoo);

            OleDbParameter pCodCupom = new OleDbParameter("CodCupom", OleDbType.VarChar);
            string codCupom = entidade.CodCupom;
            if (string.IsNullOrEmpty(codCupom))
                pCodCupom.Value = DBNull.Value;
            else
                pCodCupom.Value = codCupom;
            comando.Parameters.Add(pCodCupom);

            OleDbParameter pIdPagamento = new OleDbParameter("IdPagamento", OleDbType.Integer);
            pIdPagamento.Value = entidade.IdPagamento;
            comando.Parameters.Add(pIdPagamento);


            // Insert
            comando.ExecuteNonQuery();
            comando.Dispose();
        }

        public void Atualizar(Reserva entidade)
        {
            string sqlAtualizar = "update RESERVA set NumAssento = ?, PrecoReserva = ?, DataVenda = ?, IdPessoaCliente = ?, IdVoo = ?, CodCupom = ?, IdPagamento = ? where idReserva = ?";

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlAtualizar;

            OleDbParameter pNumAssento = new OleDbParameter("NumAssento", OleDbType.Integer);
            pNumAssento.Value = entidade.NumAssento;
            comando.Parameters.Add(pNumAssento);

            OleDbParameter pPrecoReserva = new OleDbParameter("PrecoReserva", OleDbType.Numeric);
            pPrecoReserva.Value = entidade.PrecoReserva;
            comando.Parameters.Add(pPrecoReserva);

            OleDbParameter pDataVenda = new OleDbParameter("DataVenda", OleDbType.Date);
            pDataVenda.Value = entidade.DataVenda;
            comando.Parameters.Add(pDataVenda);

            OleDbParameter pIdPessoaCliente = new OleDbParameter("IdPessoaCliente", OleDbType.Integer);
            pIdPessoaCliente.Value = entidade.IdPessoaCliente;
            comando.Parameters.Add(pIdPessoaCliente);

            OleDbParameter pIdVoo = new OleDbParameter("IdVoo", OleDbType.Integer);
            pIdVoo.Value = entidade.IdVoo;
            comando.Parameters.Add(pIdVoo);

            OleDbParameter pCodCupom = new OleDbParameter("CodCupom", OleDbType.VarChar);
            string codCupom = entidade.CodCupom;
            if (string.IsNullOrEmpty(codCupom))
                pCodCupom.Value = DBNull.Value;
            else
                pCodCupom.Value = codCupom;
            comando.Parameters.Add(pCodCupom);

            OleDbParameter pIdPagamento = new OleDbParameter("IdPagamento", OleDbType.Integer);
            pIdPagamento.Value = entidade.IdPagamento;
            comando.Parameters.Add(pIdPagamento);

            OleDbParameter pIdReserva = new OleDbParameter("IdReserva", OleDbType.Integer);
            pIdReserva.Value = entidade.IdReserva;
            comando.Parameters.Add(pIdReserva);


            // Update
            comando.ExecuteNonQuery();
            comando.Dispose();
        }

        public void RemoverPorId(int id, DbTransaction transacao)
        {
            string sqlDeletar = "delete RESERVA where IdReserva = ?";

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlDeletar;
            if (transacao != null)
                comando.Transaction = transacao as OleDbTransaction;

            OleDbParameter pId = new OleDbParameter("IdReserva", OleDbType.VarChar);
            pId.Value = id;
            comando.Parameters.Add(pId);

            // Delete
            comando.ExecuteNonQuery();
            comando.Dispose();
        }

        public Reserva BuscarPorId(int id)
        {
            Reserva registro = null;
            string sqlBuscar = "select * from RESERVA where IdReserva = " + id;

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlBuscar;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();
            if (dr.Read())
            {
                registro = ConverterDataReaderParaObj(dr);
            }
            dr.Close();
            comando.Dispose();

            if (registro != null)
                CarregarComposicao(registro);

            return registro;
        }

        private void CarregarComposicao(Reserva reserva)
        {
            int idPessoaCliente = reserva.IdPessoaCliente;
            Pessoa pessoaCliente = pessoaDAO.BuscarPorId(idPessoaCliente);
            reserva.PessoaCliente = pessoaCliente;

            int idVoo = reserva.IdVoo;
            Voo voo = vooDAO.BuscarPorId(idVoo);
            reserva.Voo = voo;

            string codCupom = reserva.CodCupom;
            Cupom cupom = cupomDAO.BuscarPorCodCupom(codCupom);
            reserva.Cupom = cupom;

            int idFormaPagamento = reserva.IdPagamento;
            FormaPagamento formaPagamento = formaPagamentoDAO.BuscarPorId(idFormaPagamento);
            reserva.FormaPagamento = formaPagamento;
        }

        private Reserva ConverterDataReaderParaObj(OleDbDataReader dr)
        {
            Reserva reserva = new Reserva();
            reserva.IdReserva = Int32.Parse(dr["IdReserva"].ToString());
            reserva.NumAssento = Int32.Parse(dr["NumAssento"].ToString());
            reserva.PrecoReserva = Decimal.Parse(dr["PrecoReserva"].ToString());
            reserva.DataVenda = DateTime.Parse(dr["DataVenda"].ToString());
            reserva.IdPessoaCliente = Int32.Parse(dr["IdPessoaCliente"].ToString());
            reserva.IdVoo = Int32.Parse(dr["IdVoo"].ToString());
            reserva.CodCupom = dr["CodCupom"].ToString();
            reserva.IdPagamento = Int32.Parse(dr["IdPagamento"].ToString());
            return reserva;
        }

        public List<Reserva> Listar()
        {
            String sqlConsulta = "select * from RESERVA";

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<Reserva> registros = new List<Reserva>();
            while (dr.Read())
            {
                Reserva registro = ConverterDataReaderParaObj(dr);
                registros.Add(registro);
            }
            dr.Close();
            comando.Dispose();

            foreach (var registro in registros)
            {
                CarregarComposicao(registro);
            }

            return registros;
        }

        public List<Reserva> ListarReservasDoVoo(int id)
        {
            String sqlConsulta = "select * from RESERVA where IdVoo = " + id;

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<Reserva> registros = new List<Reserva>();
            while (dr.Read())
            {
                Reserva registro = ConverterDataReaderParaObj(dr);
                registros.Add(registro);
            }
            dr.Close();
            comando.Dispose();

            foreach (var registro in registros)
            {
                CarregarComposicao(registro);
            }

            return registros;
        }

        public List<Reserva> ListarReservasDaPessoa(int idPessoa)
        {
            String sqlConsulta = "select * from RESERVA where IdPessoaCliente = " + idPessoa;

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<Reserva> registros = new List<Reserva>();
            while (dr.Read())
            {
                Reserva registro = ConverterDataReaderParaObj(dr);
                registros.Add(registro);
            }
            dr.Close();
            comando.Dispose();

            foreach (var registro in registros)
            {
                CarregarComposicao(registro);
            }

            return registros;
        }

        public int CalcularQntReservasParaVoo(int idVoo)
        {
            string sqlConsultar
                = "select count(*) as TOTAL from RESERVA where idvoo = " + idVoo;

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlConsultar;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            if (dr.Read())
            {
                int total = Convert.ToInt32(dr["TOTAL"]);
                dr.Close();
                comando.Dispose();
                return total;
            }

            dr.Close();
            comando.Dispose();
            throw new Exception("Erro ao recuperar o próximo ID de endereço.");
        }


        public List<LogReserva> ListarLogsReservaPorTipoModificacao(string modificacao = "D")
        {
            String sqlConsulta = "select * from LOGRESERVA where TipoModificacao = '" + modificacao + "'";

            // Configura o comando
            OleDbCommand comando = new OleDbCommand();
            comando.Connection = GerenciadorConexao.Conexao;
            comando.CommandText = sqlConsulta;

            // Select
            OleDbDataReader dr = comando.ExecuteReader();

            List<LogReserva> registros = new List<LogReserva>();
            while (dr.Read())
            {
                LogReserva registro = ConverterDataReaderParaObjLogReserva(dr);
                registros.Add(registro);
            }
            dr.Close();
            comando.Dispose();

            foreach (var registro in registros)
            {
                CarregarComposicaoLogReserva(registro);
            }

            return registros;
        }

        private void CarregarComposicaoLogReserva(LogReserva registro)
        {
            int idPessoaCliente = registro.IdPessoaCliente;
            Pessoa pessoa = pessoaDAO.BuscarPorId(idPessoaCliente);
            registro.PessoaCliente = pessoa;

            int idVoo = registro.IdVoo;
            Voo voo = vooDAO.BuscarPorId(idVoo);
            registro.Voo = voo;

            int idFormaPagamento = registro.IdPagamento;
            FormaPagamento formaPagamento = formaPagamentoDAO.BuscarPorId(idFormaPagamento);
            registro.FormaPagamento = formaPagamento;
        }

        private LogReserva ConverterDataReaderParaObjLogReserva(OleDbDataReader dr)
        {
            LogReserva registro = new LogReserva();
            registro.DataModificacao = DateTime.Parse(dr["DataModificacao"].ToString());
            registro.TipoModificacao = dr["TipoModificacao"].ToString();
            registro.IdReserva = Int32.Parse(dr["IdReserva"].ToString());
            registro.NumAssento = Int32.Parse(dr["NumAssento"].ToString());
            registro.PrecoReserva = Decimal.Parse(dr["PrecoReserva"].ToString());
            registro.DataVenda = DateTime.Parse(dr["DataVenda"].ToString());
            registro.IdPessoaCliente = Int32.Parse(dr["IdPessoaCliente"].ToString());
            registro.IdVoo = Int32.Parse(dr["IdVoo"].ToString());
            object codCupomObj = dr["CodCupom"];
            if (codCupomObj != null)
                registro.CodCupom = codCupomObj.ToString();
            registro.IdPagamento = Int32.Parse(dr["IdPagamento"].ToString());

            return registro;
        }
    }
}